import threading
import pyttsx3
import sounddevice as sd
import soundfile as sf
import queue
import keyboard
import datetime
import numpy as np
import os
import time
from aip import AipSpeech
import pyaudio
import wave
from openai import OpenAI
from spire.xls import *
from pathlib import Path
import json

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders


class ConferenceHost:

    """ 百度 的 APPID AK SK """
    APP_ID = '18397084' 
    API_KEY = 'q5VjqAAK4Tqh5ljqQSZ9WOLx'
    SECRET_KEY = 'HlERX1FcxoDW4SjKhzjyK1lymeAwmzQQ'
    
    ZHIPU_API_KEY = 'ab4891787863816b83378080d2d4c9ae.m8aFMCOqWWPPOJhz'
    
    
    def __init__(self):
        self.recording_thread = None
        self.recording_queue = queue.Queue()
        self.engine = pyttsx3.init()
        self.recording = False
        
        self.record_seconds = 10
        self.record_rate = 16000
        self.record_channels = 1
        self.record_format = pyaudio.paInt16
        self.record_chunk = 1024

        self.email_receivers = ['1104024205@qq.com', 'huangxing.daas@centerm.com']
        
        
    
    
    def run(self):
        try:
            speak_content = """
                ...启动成功...
            """
            
            self.text_to_speech(speak_content)
            
            self.start_recording()
            
            # 监听会议是否结束，如果结束则进行数据处理
            while self.recording:
                time.sleep(1)
            else:
                print("进行后续操作")
                self.next_process()

                
            print("系统提示：完结")
        except Exception as e:
            print(e)
        
    
    def next_process(self):
        # 会议结束
        time.sleep(1)
        # self.text_to_speech("会议结束...稍后会将会议纪要发送到我爸爸的邮箱；感谢各位的参与")
        self.text_to_speech("会议结束...")
        
        print(self.wav_filename)
        wav_content_dict = self.recognizer_by_baidu(self.wav_filename)
        
        if wav_content_dict['err_no'] == 0:
            wav_content = wav_content_dict['result'][0]

            print(wav_content)
            
            # 根据文件 生成本周及下周内容
            file_path = "本周模板.xlsx"
            
            text = """
                将文件里面的下周新任务，全部列出，并当做是本周的任务；并根据会议说话的内容，判断任务是否完成；格式要求：任务、执行人、完成情况、预计完成时间（日期格式，例如2024年11月5号）；
                然后再根据会议说话内容，列出下周的任务；格式和上面的相同；
                本次会议的参与人有：魏良晨、黄星、黄国栋、陈翰、李山川、陈惠、杨帆、游开威、卓其桦、汪炳志、黎昌可
                输出的格式要求是json，举例：{
                    "this_week_task": [
                        {
                            "task": "A",
                            "executor": "XX",
                            "plan_end_time": "2024-08-12",
                            "state": "未完成"
                        },
                        {
                            "task": "B",
                            "executor": "未明确指定",
                            "plan_end_time": "2024-08-12",
                            "state": "完成"
                        },
                        {
                            "task": "C",
                            "executor": "未明确指定",
                            "plan_end_time": "2024-08-12",
                            "state": "未完成"
                        }
                    ],
                    "next_week_task": [
                        {
                            "task": "D",
                            "executor": "未明确指定",
                            "plan_end_time": "2024-08-19",
                            "state": "-"
                        },
                        {
                            "task": "E",
                            "executor": "未明确指定",
                            "plan_end_time": "2024-08-19",
                            "state": "-"
                        }
                    ]
                }

                其他任何文字都不要给我
                
                会议说话的内容为:
            """
    
            final_text = text + wav_content

            # 将内容和本周内容发送给ai
            response_ai = self.file_send_to_ai(file_path,final_text)
            # 将ai给的内容 变为文件
            self.response_ai_transfer_to_excel(response_ai)

            # 发送到邮箱
            self.send_info_to_email(self.email_receivers,self.friday_date_str + "周例会","您好，附件为本周例会的生成文件，请查收",self.excel_file_name)
            
            
        else:
            print("系统提示：音频内容解析失败")
            
        
    def send_info_to_email(self,email_receivers,subject,body,attachment_path = None):
        # 发件人和收件人邮箱
        sender = '346025432@qq.com'
        receivers = email_receivers

        # 邮件内容
        subject = subject
        body = body

        # 附件的路径
        attachment_path = attachment_path

        # 创建MIMEMultipart邮件对象
        message = MIMEMultipart()
        message['From'] = sender
        message['To'] = ', '.join(receivers)  # 将收件人列表转换为逗号分隔的字符串
        message['Subject'] = subject

        # 添加邮件正文
        message.attach(MIMEText(body, 'plain', 'utf-8'))

        # 添加附件
        if attachment_path:
            with open(attachment_path, 'rb') as attachment:
                part = MIMEBase('application', 'octet-stream')
                part.set_payload(attachment.read())
            encoders.encode_base64(part)
            part.add_header('Content-Disposition', 'attachment', filename=attachment_path)
            message.attach(part)

        # SMTP服务器信息
        smtp_server = 'smtp.qq.com'
        smtp_port = 587  # 或者使用465端口，取决于是否使用SSL
        smtp_username = sender  # 通常是你的QQ邮箱
        smtp_password = 'fcdsbuerkgnxbiee'

        # 创建SMTP对象并开始TLS加密传输
        server = smtplib.SMTP(smtp_server, smtp_port)
        server.starttls()

        # 登录SMTP服务器
        server.login(smtp_username, smtp_password)

        # 发送邮件
        server.sendmail(sender, receivers, message.as_string())

        # 断开服务器连接
        server.quit()

    def file_send_to_ai(self,file_path,text):
        print("###系统提示：AI大模型处理中...")
        
        client = OpenAI(
            api_key = "sk-dlwCiNCL54ebpt30BBNe728WBePcBXS9igZDAlwtGYTPIGwi",
            base_url = "https://api.moonshot.cn/v1",
        )
        
        # xlnet.pdf 是一个示例文件, 我们支持 pdf, doc 以及图片等格式, 对于图片和 pdf 文件，提供 ocr 相关能力
        file_object = client.files.create(file=Path(file_path), purpose="file-extract")
        
        # 获取结果
        # file_content = client.files.retrieve_content(file_id=file_object.id)
        # 注意，之前 retrieve_content api 在最新版本标记了 warning, 可以用下面这行代替
        # 如果是旧版本，可以用 retrieve_content
        file_content = client.files.content(file_id=file_object.id).text
        
        # 把它放进请求中
        messages = [
            {
                "role": "system",
                "content": "你是 Kimi，由 Moonshot AI 提供的人工智能助手，你更擅长中文和英文的对话。你会为用户提供安全，有帮助，准确的回答",
            },
            {
                "role": "system",
                "content": file_content,
            },
            {"role": "user", "content": text},
        ]
        
        # 然后调用 chat-completion, 获取 Kimi 的回答
        completion = client.chat.completions.create(
        model="moonshot-v1-32k",
        messages=messages,
        temperature=0.3,
        )
        
        print(completion.choices[0].message.content)
        print("###系统提示：AI大模型处理完毕")
        return completion.choices[0].message.content
        
        
    
    def response_ai_transfer_to_excel(self,response_ai):
        # 首先尝试将 response_ai 转换成字典，假设它是 JSON 格式的字符串
        if isinstance(response_ai, str):
            try:
                response_ai = json.loads(response_ai)
            except json.JSONDecodeError as e:
                print(f"### 错误：无法解析 response_ai 为字典: {e}")
                return

        # 确保 response_ai 是字典
        if not isinstance(response_ai, dict):
            print("### 错误：response_ai 不是字典")
            return

        data = response_ai
        
        print("### 系统提示：正在生成 Excel 文件...")
        wb = Workbook()
        wb.LoadFromFile("template.xlsx")

        sheet = wb.Worksheets[0]
        
        # 计算本周一和本周五的日期
        today = datetime.datetime.today()
        weekday = today.weekday()  # 0=Monday, 6=Sunday
        monday = today - datetime.timedelta(days=weekday)
        friday = monday + datetime.timedelta(days=4)

        # 格式化日期
        monday_str = monday.strftime('%m月%d')
        friday_str = friday.strftime('%m月%d')
        all_friday_str = friday.strftime('%Y-%m-%d')
        # 创建会议标题
        meeting_title = f"{monday_str}-{friday_str}例会"

        sheet.Range["B3"].Text = meeting_title
        sheet.Range["B4"].Text = all_friday_str

        
        this_week_template_row = sheet.Rows[7]
        next_week_template_row = sheet.Rows[8]
        first_row_index = 10
        row_index = first_row_index

        # 确保 data 包含 "this_week_task" 和 "next_week_task"
        if "this_week_task" in data:
            for task in data["this_week_task"]:
                sheet.CopyRow(this_week_template_row, sheet, row_index, CopyRangeOptions.All)
                sheet.Range[f"B{row_index}"].Text = f"{task.get('task', '')};--{task.get('state', '')}"
                sheet.Range[f"F{row_index}"].Text = task.get("executor", '')
                sheet.Range[f"G{row_index}"].Text = task.get("plan_end_time", '')
                row_index += 1

        if row_index - 1 > first_row_index:
            sheet.Range[f"A{first_row_index}:A{row_index - 1}"].Merge()

        first_row_index = row_index
        if "next_week_task" in data:
            for task in data["next_week_task"]:
                sheet.CopyRow(next_week_template_row, sheet, row_index, CopyRangeOptions.All)
                sheet.Range[f"B{row_index}"].Text = task.get("task", '')
                sheet.Range[f"F{row_index}"].Text = task.get("executor", '')
                sheet.Range[f"G{row_index}"].Text = task.get("plan_end_time", '')
                row_index += 1
        if row_index - 1 > first_row_index:
            sheet.Range[f"A{first_row_index}:A{row_index - 1}"].Merge()
        sheet.DeleteRow(8, 2)

        self.friday_date_str = self.friday_date()

        excel_file_name = f"{self.friday_date_str}周例会-创新发展部.xlsx"
        
        wb.SaveToFile(excel_file_name)
        
        self.excel_file_name = excel_file_name
        
        print("### 系统提示：Excel 生成完毕")
    
    def friday_date(self):
        # 获取当前日期
        today = datetime.datetime.now()

        # 计算今天是周几（Monday=0, Sunday=6）
        today_weekday = today.weekday()

        # 计算到本周五的天数
        friday_weekday = 4  # Friday is the 4th day of the week (0-6 index)
        days_to_friday = (friday_weekday - today_weekday) % 7

        # 计算本周五的日期
        friday = today + datetime.timedelta(days=days_to_friday)

        # 格式化日期为 YYYYMMDD 格式
        friday_date_str = friday.strftime('%Y%m%d')
        
        # 打印并返回格式化的日期字符串
        print(friday_date_str)
        return friday_date_str


    
    def record_audio(self):
        
        p = pyaudio.PyAudio()

        stream = p.open(format=self.record_format,
                        channels=self.record_channels,
                        rate=self.record_rate,
                        input=True,
                        frames_per_buffer=self.record_chunk)

        
        
        frames = []

        while self.recording:
            data = stream.read(self.record_chunk)
            frames.append(data)


        stream.stop_stream()
        stream.close()
        p.terminate()
        
        # Get current time
        now = datetime.datetime.now()
        # Format date time
        date_str = now.strftime("%Y%m%d_%H%M%S")
        
        # Set default audio directory
        default_audio_dir = "wavlog/"
        # Create date folder
        audio_dir = os.path.join(default_audio_dir, now.strftime("%Y%m%d"))
        os.makedirs(audio_dir, exist_ok=True)  # If it doesn't exist, create it
        
        # Set filename
        wav_filename = f"{date_str}.wav"
        # Set full path
        self.wav_filename = os.path.join(audio_dir, wav_filename)
        
        # Save as WAV file
        wf = wave.open(self.wav_filename, 'wb')
        wf.setnchannels(self.record_channels)
        wf.setsampwidth(p.get_sample_size(self.record_format))
        wf.setframerate(self.record_rate)
        wf.writeframes(b''.join(frames))
        wf.close()
        
        return self.wav_filename
    
    
    # 百度语音识别器
    def recognizer_by_baidu(self,record_filename):
        
        client = AipSpeech(self.APP_ID, self.API_KEY, self.SECRET_KEY)

        # 读取文件
        def get_file_content(filePath):
            with open(filePath, 'rb') as fp:
                return fp.read()

        # 识别本地文件
        res = client.asr(get_file_content(record_filename), 'wav', 16000, {
            'dev_pid': 1537,
        })

        print(res)        
        # print(type(res))
        
        # print(res['err_no'])
        # print(res['result'][0])
        
        return res
            
        
    # 文字转语音
    def text_to_speech(self, text):
        print("开始语音播报...")
        self.engine.say(text)
        self.engine.runAndWait()
        print("语音播报结束")
# 
    # 开始录音
    def start_recording(self):
        self.recording = True
        self.recording_thread = threading.Thread(target=self.record_audio)
        self.recording_thread.daemon = False  # 设置线程不是守护线程
        self.recording_thread.start()
        print("开始录音...")

        # 监听 CTRL+t 组合键
        keyboard.add_hotkey('ctrl+t', self.stop_recording)

    # 停止录音
    def stop_recording(self):
        
        self.recording = False
        print("录音已停止")

        

    
        
    # 录音功能
    def record_audio111(self):
        fs = 44100  # Sample rate
        seconds = 0  # Record indefinitely until stopped
        myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=2, blocking=False)
        while self.recording:
            try:
                data = sd.rec(int(0.1 * fs), samplerate=fs, channels=2, blocking=True)
                sd.wait()
                if not self.recording:
                    break
                myrecording = np.append(myrecording, data, axis=0)
            except KeyboardInterrupt:
                break
        
            
        sd.stop()

        # 获取当前时间
        now = datetime.now()
        # 格式化日期时间
        date_str = now.strftime("%Y%m%d_%H%M%S")
        
        # 设置默认音频目录
        default_audio_dir = "wavlog/"
        # 创建日期文件夹
        audio_dir = os.path.join(default_audio_dir, now.strftime("%Y%m%d"))
        os.makedirs(audio_dir, exist_ok=True)  # 如果不存在则创建
        
        # 设置文件名
        wav_filename = f"{date_str}.wav"
        # 设置完整路径
        self.filename = os.path.join(audio_dir, wav_filename)
        
        # 写入文件
        sf.write(self.filename, myrecording, fs)
        print(f"录音文件已保存为 {self.filename}")
        


        
# 使用示例
if __name__ == "__main__":
    host = ConferenceHost()
    host.run()
    # 等待录音线程结束
    if host.recording_thread is not None:
        host.recording_thread.join()